import multiprocessing
import os
import traceback
from datetime import datetime

import pandas as pd
from catboost import CatBoostClassifier
from xbase_util.common_util import date2s

from src.bean.circle_task_bean import CircleTaskBean
from src.bean.model_database_enum import ModelDatabaseEnum
from src.bean.x_typing import PRE_HANDLE_TYPE
from src.constant import expression, expression_tag, predict_logger, project_root_path
from src.model.common.model_list import print_model_list_entrance
from src.model.model_common_util import extract_predict_error
from src.model.v1.v1_predict import v1_start_get_session_queue, start_capture_queue
from src.model.v2.v2_pre_handle import v2_file_pre_handle
from src.util.common_util import is_int, while_input, printx, input_is_yes, is_valid_datetime


def v2_start_predict_queue(predict_queue, old_model, model):
    total_abnormal = 0
    total_normal = 0
    while True:
        try:
            session, start_time, end_time = predict_queue.get()
            predict_logger.info(f"[文件预测]预测队列收到数据：{len(session)}")
            df, cluster, df2 = v2_file_pre_handle(pd.DataFrame(session), model_id=old_model[ModelDatabaseEnum.id.value],
                                                  handle_type=PRE_HANDLE_TYPE.predict)
            x_data = df[[item for item in df.columns.tolist() if item != 'is_dangerous']]
            y_pred = model.predict(x_data)
            result_normal = sum(1 for item in y_pred if f'{item}' == '0')
            result_abnormal = sum(1 for item in y_pred if f'{item}' == '1')
            total_abnormal += result_abnormal
            total_normal += result_normal
            predict_logger.info(
                f"[文件预测]异常有{result_abnormal}个，共{total_abnormal}个｜正常有{result_normal}个，共{total_normal}个")
            data, normal_data_predict_as_abnormal, abnormal_data_predict_as_normal = extract_predict_error(df2, y_pred)
            if len(data) != 0:
                f = os.path.join(project_root_path, "data",
                                 f"realtime_predict_error_{date2s(datetime.now(), '%m_%d_%H_%M')}.csv")
                data.to_csv(f, index=False)
                predict_logger.info(f"保存{normal_data_predict_as_abnormal}/{len(data)}条数据")
        except Exception as e:
            print(f"[文件预测]{e}")
            traceback.print_exc()
            predict_logger.info(f"[文件预测]{e}")


def v2_predict_realtime_entrance(config):
    model_list = config.get_model_list()
    start_time = None
    time_before_now_m = None
    print_model_list_entrance(config)
    num = while_input("请输入要预测的模型id:", is_int)
    models = [model for model in model_list if f'{model[ModelDatabaseEnum.id.value]}' == f'{num}']
    if len(models) == 0:
        printx("模型不存在")
        return None
    old_model = models[0]
    if input_is_yes("是否使用固定的开始时间"):
        start_time = while_input("请输入开始时间:", is_valid_datetime)
    else:
        time_before_now_m = while_input("请输入前几分钟作为开始时间:", is_int)
    time_span_s = while_input("请输每次获取几秒的数据:", is_int)
    sleep_s = while_input("请输每次获取完成间隔几秒:", is_int)
    capture_queue = multiprocessing.Queue()
    predict_queue = multiprocessing.Queue()
    exp = expression[expression_tag]
    model = CatBoostClassifier()
    model.load_model(old_model[ModelDatabaseEnum.model_path.value])
    multiprocessing.Process(target=v2_start_predict_queue, args=(predict_queue, old_model, model)).start()
    print(exp)
    multiprocessing.Process(target=start_capture_queue, args=(capture_queue, predict_queue, config, exp)).start()
    v1_start_get_session_queue(CircleTaskBean(
        start_time=start_time,
        time_before_now_m=time_before_now_m,
        time_span_s=time_span_s,
        sleep_s=sleep_s
    ), capture_queue)
